#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QLabel>
#include <QProgressBar>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QThread>
#include <QElapsedTimer>
#include <QDateTime>
#include <QObject>
#include<QTimer>
// 1. 定义子线程任务类（负责耗时计算，不涉及UI操作）
class HeavyTaskWorker : public QObject {
    Q_OBJECT

public:
    HeavyTaskWorker(QObject *parent = nullptr) : QObject(parent) {}

public slots:
    // 子线程执行的耗时操作
    void doHeavyWork() {
        QElapsedTimer timer;
        timer.start();

        // 模拟超级耗时操作（50亿次循环）
        volatile long long result = 0;
        long long *largeArray = new long long[100000];

        for (long long i = 0; i < 5000000000; ++i) {
            // 内层循环增加计算量
            for (int j = 0; j < 10; ++j) {
                result += (i * j) % (i + 1);
            }
            // 内存访问操作
            if (i % 1000 == 0) {
                largeArray[i % 100000] = result;
            }
            // 每完成5%进度，发送信号通知主线程更新进度条
            if (i % 500000000 == 0) { // 50亿 / 100 = 5亿，每5亿次更新1%
                int progress = static_cast<int>(i / 50000000); // 计算进度（0-100）
                emit progressUpdated(progress);
            }
        }

        delete[] largeArray;
        // 发送最终结果（总耗时）
        emit workFinished(timer.elapsed());
    }

signals:
    // 发送进度更新信号（子线程→主线程）
    void progressUpdated(int progress);
    // 发送任务完成信号（携带耗时）
    void workFinished(qint64 elapsedTime);
};

// 2. 主窗口类（只负责UI，通过信号槽与子线程通信）
class SmoothDemoWindow : public QMainWindow {
    Q_OBJECT

public:
    SmoothDemoWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
        setWindowTitle("解决UI卡顿：子线程处理耗时操作");
        setMinimumSize(600, 300);

        // 创建UI组件
        QWidget *centralWidget = new QWidget(this);
        QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
        mainLayout->setSpacing(20);

        statusLabel = new QLabel("当前状态：空闲\n点击按钮开始任务，可同时拖动窗口、点击测试按钮", this);
        statusLabel->setStyleSheet("font-size: 14px; border: 1px solid #ccc; padding: 10px;");
        mainLayout->addWidget(statusLabel);

        progressBar = new QProgressBar(this);
        progressBar->setRange(0, 100);
        progressBar->setValue(0);
        mainLayout->addWidget(progressBar);

        timeLabel = new QLabel("当前时间：" + QDateTime::currentDateTime().toString(), this);
        timeLabel->setStyleSheet("color: blue;");
        mainLayout->addWidget(timeLabel);

        QHBoxLayout *buttonLayout = new QHBoxLayout();
        startButton = new QPushButton("开始耗时操作（子线程）", this);
        startButton->setStyleSheet("font-size: 16px; padding: 10px;");
        buttonLayout->addWidget(startButton);

        testButton1 = new QPushButton("测试按钮1", this);
        buttonLayout->addWidget(testButton1);

        testButton2 = new QPushButton("测试按钮2", this);
        buttonLayout->addWidget(testButton2);

        mainLayout->addLayout(buttonLayout);
        setCentralWidget(centralWidget);

        // 定时器更新时间（验证UI是否流畅）
        timeTimer = new QTimer(this);
        timeTimer->start(1000);
        connect(timeTimer, &QTimer::timeout, this, [=]() {
            timeLabel->setText("当前时间：" + QDateTime::currentDateTime().toString());
        } ,Qt::DirectConnection);  //同一个线程用DirectConnection

        // 连接测试按钮点击事件（验证UI响应）
        connect(testButton1, &QPushButton::clicked, this, [=]() {
            statusLabel->setText(statusLabel->text() + "\n测试按钮1被点击");
        },Qt::DirectConnection);
        connect(testButton2, &QPushButton::clicked, this, [=]() {
            statusLabel->setText(statusLabel->text() + "\n测试按钮2被点击");
        } ,Qt::DirectConnection);

        // 3. 初始化子线程和任务对象
        workerThread = new QThread(this);
        worker = new HeavyTaskWorker();//未指定parent，默认nullptr

         // 关键：moveToThread将 worker 的线程亲和性改为子线程,否则worker 默认属于主线程 doHeavyWork 会在主线程中执行，直接阻塞 UI 事件循环，导致界面卡顿
        // 将任务对象移到子线程 ,指定该对象的成员函数（尤其是槽函数）在哪个线程中执行
        worker->moveToThread(workerThread);

        // 连接信号槽（关键：线程间通信）
        // 主线程→子线程：点击按钮启动任务（跨线程）
        connect(startButton, &QPushButton::clicked, this, &SmoothDemoWindow::onStartTask ,Qt::DirectConnection); //同一个线程
        connect(this, &SmoothDemoWindow::startWork, worker, &HeavyTaskWorker::doHeavyWork ,Qt::QueuedConnection);//（跨线程）

        // 子线程→主线程：更新进度（跨线程）
        connect(worker, &HeavyTaskWorker::progressUpdated, this, [=](int progress) {
            progressBar->setValue(progress);
            statusLabel->setText(QString("当前状态：处理中... 进度：%1%")
                                 .arg(progress));
        }  , Qt::QueuedConnection);

        // 子线程→主线程：任务完成（跨线程）
        connect(worker, &HeavyTaskWorker::workFinished, this, [=](qint64 elapsed) {
            statusLabel->setText(QString("当前状态：任务完成！总耗时：%1 毫秒")
                                 .arg(elapsed));
            progressBar->setValue(100);
            startButton->setEnabled(true);
            // 任务完成后退出子线程
            workerThread->quit();
        } ,  Qt::QueuedConnection);

        // 子线程结束后释放任务对象 (跨线程)
        connect(workerThread, &QThread::finished, worker, &QObject::deleteLater , Qt::QueuedConnection);
    }

    // 窗口关闭时确保线程退出
    ~SmoothDemoWindow() {
        workerThread->quit();
        workerThread->wait(); // 等待线程安全退出
    }

private slots:
    // 启动任务（主线程中调用）
    void onStartTask() {
        statusLabel->setText("当前状态：开始执行任务（子线程中）...");
        startButton->setEnabled(false);
        progressBar->setValue(0);
        // 启动子线程并开始工作
        workerThread->start();
        emit startWork(); // 触发子线程任务
    }

signals:
    // 用于触发子线程任务的信号
    void startWork();

private:
    QLabel *statusLabel;
    QLabel *timeLabel;
    QProgressBar *progressBar;
    QPushButton *startButton;
    QPushButton *testButton1;
    QPushButton *testButton2;
    QTimer *timeTimer;

    // 线程相关
    QThread *workerThread;   // 子线程
    HeavyTaskWorker *worker; // 任务对象
};

// 程序入口
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    SmoothDemoWindow window;
    window.show();

    return app.exec();
}

#include "main.moc"
